/*
 EmonTx Shield 4 x CT example
 
 An example sketch for the emontx Arduino shield module for
 CT only electricity monitoring.
 
 Part of the openenergymonitor.org project
 Licence: GNU GPL V3
 
 Authors: Glyn Hudson, Trystan Lea
 Builds upon JeeLabs RF12 library and Arduino
 
 emonTx documentation: 	http://openenergymonitor.org/emon/modules/emontxshield/
 emonTx firmware code explination: http://openenergymonitor.org/emon/modules/emontx/firmware
 emonTx calibration instructions: http://openenergymonitor.org/emon/modules/emontx/firmware/calibration
 
 THIS SKETCH REQUIRES:
 
 Libraries in the standard arduino libraries folder:
 	- JeeLib		https://github.com/jcw/jeelib
 	- EmonLib		https://github.com/openenergymonitor/EmonLib.git
 
 Other files in project directory (should appear in the arduino tabs above)
 	- emontx_lib.ino
 
 */

/*Recommended node ID allocation
 ------------------------------------------------------------------------------------------------------------
 -ID-	-Node Type- 
 0	- Special allocation in JeeLib RFM12 driver - reserved for OOK use
 1-4     - Control nodes 
 5-10	- Energy monitoring nodes
 11-14	--Un-assigned --
 15-16	- Base Station & logging nodes
 17-30	- Environmental sensing nodes (temperature humidity etc.)
 31	- Special allocation in JeeLib RFM12 driver - Node31 can communicate with nodes on any network group
 -------------------------------------------------------------------------------------------------------------
 */

#include <JeeLib.h>
#include "EmonLib.h"

//  Time (ms) to allow the filters to settle before sending data
const int FILTERSETTLETIME =5000;

// Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.
#define FREQ RF12_433MHZ
// emonTx RFM12B node ID
const int nodeID = 10;
// emonTx RFM12B wireless network group - needs to be same as emonBase and emonGLCD
const int networkGroup = 210;

double lastUpdate=0;
//the bigger EPSILON is, the larger variance we are ignoring as noise
const double EPSILON=.009;
const double MIN_UPDATE_MS=5000;

bool areSame(double a, double b)
{
  return fabs(a - b) < EPSILON;
}

// Create  instances for each CT channel
EnergyMonitor ct1,ct2;

typedef struct {
  float power1, power2, power3, power4;
}
PayloadTX;      // create structure - a neat way of packaging data for RF comms
PayloadTX emontx,lastemontx;

// On-board emonTx LED
const int LEDpin = 9;

boolean settled = false;

const float VOLTS=124.0;

void setup()
{
  Serial.begin(9600);
  Serial.println("emonTX Shield CT123 example");
  Serial.println("OpenEnergyMonitor.org");
  Serial.print("Node: ");
  Serial.print(nodeID);
  Serial.print(" Freq: ");
  if (FREQ == RF12_433MHZ) Serial.print("433Mhz");
  if (FREQ == RF12_868MHZ) Serial.print("868Mhz");
  if (FREQ == RF12_915MHZ) Serial.print("915Mhz");
  Serial.print(" Network: ");
  Serial.println(networkGroup);

  // Setup emonTX CT channel (channel, calibration)
  // Calibration factor = CT ratio / burden resistance
  // emonTx Shield Calibration = (100A / 0.05A) / 33 Ohms
  //correct reading/emontx reading * current calibration
  //.25/.08
  ct1.current(1, 347.0);

  // initialize RFM12B
  rf12_initialize(nodeID, FREQ, networkGroup);
  rf12_sleep(RF12_SLEEP);

  // Setup indicator LED
  pinMode(LEDpin, OUTPUT);
  digitalWrite(LEDpin, HIGH);
}

void send_rf_data()
{
  rf12_sleep(RF12_WAKEUP);
  // if ready to send + exit loop if it gets stuck as it seems too
  int i = 0; 
  while (!rf12_canSend() && i<10) {
    rf12_recvDone(); 
    i++;
  }
  rf12_sendStart(0, &emontx, sizeof emontx);
  // set the sync mode to 2 if the fuses are still the Arduino default
  // mode 3 (full powerdown) can only be used with 258 CK startup fuses
  //rf12_sendWait(2);
  //rf12_sleep(RF12_SLEEP);
}

void loop()
{
  //ct.calcIrms(number of wavelengths sample)*AC RMS voltage
  emontx.power1 = ct1.calcIrms(1480);
  Serial.print(emontx.power1,3);

  Serial.println();
  delay(100);

  // because millis() returns to zero after 50 days !
  if (!settled && millis() > FILTERSETTLETIME) {
    settled = true;
  }

  // send data only after filters have settled
  if (settled && (!areSame(lastemontx.power1,emontx.power1) || millis()-MIN_UPDATE_MS>lastUpdate))
  {
    lastemontx.power1=emontx.power1;
    lastUpdate=millis();
    // *SEND RF DATA* - see emontx_lib
    digitalWrite(LEDpin, HIGH);
    send_rf_data();
    // flash LED

    delay(200-(millis()-lastUpdate));
    digitalWrite(LEDpin, LOW);
    // delay between readings in ms
    delay(2000);
  }
}
